Skip to content

Conversation

@RomarQ
Copy link
Contributor

@RomarQ RomarQ commented Oct 28, 2025

Part of #2415
Closes #2436

Related: #6325 #6326

Summary

Deprecates the ValidateUnsigned trait and #[pallet::validate_unsigned] attribute in favor of the new TransactionExtension API. This is a non-breaking change that adds deprecation warnings to guide users toward the modern transaction validation approach.

Migratees pallet-example-offchain-worker to use the TransactionExtension API.

Motivation

The ValidateUnsigned trait was the legacy approach for validating unsigned transactions in FRAME pallets. The newer TransactionExtension trait provides a more flexible and composable way to handle transaction validation, including both signed and unsigned transactions.

Changes

Deprecated APIs

  • ✅ Added #[deprecated] attribute to ValidateUnsigned trait
  • ✅ Added deprecation warning to #[pallet::validate_unsigned] macro attribute

Migration (Using TransactionExtensions)

https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/transaction_extensions

Impact

  • Non-breaking: Existing code continues to work with deprecation warnings
  • Compiler warnings: Users will see deprecation notices guiding them to migrate
  • Timeline: Full removal planned for a future major release (TBD)

Review Notes

  • The #[pallet::validate_unsigned] deprecation warning might be redundant since it's always used together with ValidateUnsigned, but both are included for completeness and clarity.

Follow-up Tasks

The following pallets and crates need to be migrated to TransactionExtension in subsequent PRs:

Runtime crates:

  • polkadot-runtime-common
  • polkadot-runtime-parachains

FRAME pallets:

  • pallet-babe
  • pallet-beefy
  • pallet-election-provider-multi-block
  • pallet-grandpa
  • pallet-im-online
  • pallet-mixnet

Core:

  • frame-executive
  • frame-system

Examples:

  • pallet-example-offchain-worker

Testing:

  • substrate-test-runtime

Open Question

Should we remove the ValidateUnsigned bound from the type parameter V in the Applyable trait?

@RomarQ RomarQ changed the title Deprecate validate unsigned Deprecate ValidateUnsigned trait and #[pallet::validate_unsigned] attribute Oct 28, 2025
@RomarQ RomarQ marked this pull request as ready for review October 28, 2025 17:02
@RomarQ RomarQ requested review from a team and acatangiu as code owners October 28, 2025 17:02
@gui1117
Copy link
Contributor

gui1117 commented Oct 29, 2025

For information there I had 2 PR to upgrade usage to authorize call:

I also think it is actually somewhat a breaking change. Even if the old flow with unsigned transaction is kept, using a different transaction may break indexers and application monitoring the chain through those extrinsics.
It is also why I didn't push it.

IMO validate_unsigned is also ok, this is why I didn't push it, but examples should definitely show authorize call and general transactions flow.

@RomarQ
Copy link
Contributor Author

RomarQ commented Oct 29, 2025

For information there I had 2 PR to upgrade usage to authorize call:

I also think it is actually somewhat a breaking change. Even if the old flow with unsigned transaction is kept, using a different transaction may break indexers and application monitoring the chain through those extrinsics. It is also why I didn't push it.

IMO validate_unsigned is also ok, this is why I didn't push it, but examples should definitely show authorize call and general transactions flow.

Hi @gui1117,

Agreed, these 2 PR's you mentioned complement this one. What is blocking them?

@gui1117
Copy link
Contributor

gui1117 commented Oct 30, 2025

Agreed, these 2 PR's you mentioned complement this one. What is blocking them?

Because I think it is unnecessary breaking change.

In general I don't think we should deprecate ValidateUnsigned, now that the transaction pool is fork-aware there is no need to remove it, the transaction pool was the only reason we wanted to differentiate between inherents and unsigned transactions, now I don't see any reason to remove unsigned transactions.

Every time we deprecate something it involves extra work for everybody using the feature. I don't see it as necessary.

@RomarQ
Copy link
Contributor Author

RomarQ commented Oct 31, 2025

Agreed, these 2 PR's you mentioned complement this one. What is blocking them?

Because I think it is unnecessary breaking change.

In general I don't think we should deprecate ValidateUnsigned, now that the transaction pool is fork-aware there is no need to remove it, the transaction pool was the only reason we wanted to differentiate between inherents and unsigned transactions, now I don't see any reason to remove unsigned transactions.

Every time we deprecate something it involves extra work for everybody using the feature. I don't see it as necessary.

The main concern is that the SDK now needs to maintain multiple mechanisms for achieving the same goal, which increases complexity and makes the codebase harder to maintain and document consistently.

Ideally, there should be a single, recommended way to validate unsigned transactions. That mechanism should be well-maintained and clearly documented.

I agree that the new extension mechanism currently lacks documentation, and requiring runtime developers to explicitly include frame_system::AuthorizeCall is not ideal. It might make sense to enable this extension by default, or alternatively, emit a compilation error if a pallet requires and the extension is not explicitly set in the runtime definition.

@gui1117
Copy link
Contributor

gui1117 commented Oct 31, 2025

I agree that the new extension mechanism currently lacks documentation, and requiring runtime developers to explicitly include frame_system::AuthorizeCall is not ideal. It might make sense to enable this extension by default, or alternatively, emit a compilation error if a pallet requires and the extension is not explicitly set in the runtime definition.

This is hard because frame-executive only require an applyable implementation. The definition of the transaction extension is not accessible by Frame.

Maybe there is a way to make an integrity test.

Note that everytime a pallet defines an extension this extension can also be missed during the runtime configuration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deprecate ValidateUnsigned and #[validate_unsigned]

2 participants